<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .file-box {
            display: inline-block;
            width: 160px;
            height: 160px;
            border: 1px solid #aaa;
            background-color: #dedede;
            cursor: pointer;
            position: relative;
        }

        .file-box>input[type='file'] {
            display: none;
        }

        .file-box>img {
            width: 100%;
            height: 100%;
            overflow: hidden;
            object-fit: scale-down;
            object-position: center;
        }

        .file-box .loading {
            position: absolute;
            top: 0px;
            left: 0px;
            background-color: rgba(0, 0, 0, 0.4);
            object-fit: scale-down;
            object-position: center;
            z-index: 2;
        }

        .upload-box{
            display: inline-block;
            width: 160px;
            height: 160px;
            border: 1px solid #aaa;
            background-color: #dedede;
            cursor: pointer;
            position: relative;
        }
        .upload-box .file1-box{
            display: inline-block;
            width: 100%;
            height: 100%;
        }
        .upload-box .file1-box>input[type='file'] {
            display: none;
        }

        .upload-box .file1-box>img {
            width: 100%;
            height: 100%;
            overflow: hidden;
            object-fit: scale-down;
            object-position: center;
        }
        .upload-box .loading {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.8);
            object-fit: scale-down;
            object-position: center;
            z-index: 2;
            padding: 10px;
            box-sizing: border-box;
            display: flex;
            align-items: center;
        }
        .upload-box .progress-box{
            width: 100%;
            height: 22px;
            line-height: 22px;
            border: 1px solid white;
            box-sizing: border-box;
            text-align: center;
            font-size: 0px;
        }
        .upload-box .progress{
            height: 100%;
            width: 0%;
            font-size: 12px;
            color: white;
            background-color: green;
        }
    </style>
</head>

<body>
    <div id="app">
        <!-- label 和 input 父子关联触发不是事件冒泡触发，而特殊关联性触发，所以使用阻止事件冒泡是不能终端label对input的调用 -->
        <!-- <label class="file-box">
            <img v-show="isShowLoading" class="loading" src="../assets/img/loading.gif" @click.stop>
            <img :src="file.path">
            <input type="file" @change="chooseFile($event.target)">
        </label> -->
        <!-- 修正问题 -->
        <div class="upload-box">
            <!-- <img v-show="isShowLoading" class="loading" src="../assets/img/loading.gif"> -->
            <div v-show="isShowLoading" class="loading">
                <div class="progress-box">
                    <div class="progress" :style="`width:${getProgress}%;`">{{ getProgress }}%</div>
                </div>
            </div>
            <label class="file1-box">
                <img :src="file.path">
                <input type="file" @change="chooseFile($event.target)">
            </label>
        </div>
        <!-- 
            受控[文件类型，文件大小] 
                只有 png jpg jpeg bmp gif 图片可以上传
                文件必须在 1M 以内 ( 1*1024kb , 1*1024*1024字节 )
            完成真实上传 （axios = post 文件上传操作）
        -->
        <pre>{{ typeCheck }}</pre>
        <!-- 
        disabled 条件判断选择计算属性
            + 判断条件复杂，如果写在模板中难以维护。
            + 如果使用方法完成操作，页面其它变量更新会导致方法多次执行。
        v-on 动态事件绑定
            + v-on:[动态事件变量] 语法不接受表达式，只能使用仓库变量
            + 该案例中 动态事件变量的 变化需要依赖一套复杂的判断逻辑
         -->
        <input type="button" value="文件上传" :disabled="!typeCheck" @[eventname]="uploadFile()">

    </div>
    <script type="module">
        
        import { createApp } from "../assets/vue3/vue.esm-browser.js";
        import axios from "../assets/axios/axios.js";
        createApp({
            data () {
                return {
                    isShowLoading:false,
                    progress:0,
                    file: {
                        path: "../assets/img/update (1).png",
                        blob: null
                    },
                    // e:""
                }
            },
            computed: {
                getProgress(){
                    return Math.ceil( this.progress>1?this.progress-1:0 )
                },
                typeCheck () {
                    // 获取文件大小(字节) - 初始时 blob 可能为空，所以增加三木判断防止程序报错
                    let size = this.file.blob ? this.file.blob.size : 0;
                    // 获取文件类型
                    let type = this.file.blob ? this.file.blob.type : "";
                    // 文件类型的允许列表
                    const arr = ["image/jpeg", "image/png", "image/gif", "image/bmp"];
                    // 判断文件类型是否符合要求，大小是否符合要求
                    let flag = arr.includes(type) && size <= 1 * 1024 * 1024;
                    // if(flag){
                    //     this.e="click"
                    // }else{
                    //     this.e = "";
                    // }
                    return flag
                },
                // 计算属性和普通仓库变量一样，在方法中可以直接通过 this 访问
                eventname () {
                    return this.typeCheck ? "click" : ""
                }
            },
            methods: {
                chooseFile (fileDom) {
                    let file = fileDom.files[0];
                    console.log(file)
                    this.file.path = window.URL.createObjectURL(file);
                    this.file.blob = file;
                },
                uploadFile () {
                    this.isShowLoading = true;
                    // ajax 文件上传必须将二进制文件 以 FormData 对象进行包裹，并提供multipart/form-data请求头
                    let fd = new FormData();
                    // 添加文件参数，其中 img 参数名由服务器决定的
                    fd.append("img", this.file.blob)
                    axios({
                        // 地址
                        url: "http://127.0.0.1:3000/api/files",
                        // 类型 - 文件上传必须选择 具有请求体的请求
                        method: "post",
                        // data 请求体参数
                        data: fd,
                        // params 请求地址参数
                        // params:{},
                        // `onUploadProgress` 允许为上传处理进度事件
                        // 浏览器专属
                        onUploadProgress: (progressEvent) => {
                            // 处理原生进度事件
                            console.log(progressEvent)
                            console.log(progressEvent.loaded/progressEvent.total*100+"%")
                            this.progress = progressEvent.loaded/progressEvent.total*100;
                        }
                    }).then((response) => {
                        // 返回的结果是 axios 二次封装的整合结果 【响应数据、请求的对象、网络的状态……】
                        console.log(response.data)
                    }).catch((error) => {
                        console.log(error)
                    }).finally(()=>{
                        this.isShowLoading = false;
                        this.progress = 0;
                    })
                }
            },
        }).mount("#app")
    </script>
</body>

</html>